package com.cold.demo.template.test;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.tomcat.jni.Local;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.math.BigDecimal;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.text.spi.DateFormatProvider;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * 知苗预约
 */
public class GrabHPVForXF_ZMYY_Finally {

    public static final Logger log = LoggerFactory.getLogger(GrabHPVForXF_ZMYY_Finally.class.getSimpleName());

    private static volatile Map<String, List<String>> headers;
    private static final String serverUrl = "https://cloud.cn2030.com/sc/wx/HandlerSubscribe.ashx";
    private static final ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    static {
        generateHeader();

    }

    private static Map<String, List<String>> generateHeader() {
        if (headers != null) {
            return headers;
        }
        String sql = "Host: cloud.cn2030.com\n" +
                "Connection: keep-alive\n" +
                "Cookie: ASP.NET_SessionId=xgtcpwxco4c4zstefq1pbsjg\n" +
                "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat\n" +
                "content-type: application/json\n" +
                "zftsl: cab9ac6501461bd7759722c01429f518\n" +
                "Referer: https://servicewechat.com/wx2c7f0f3c30d99445/88/page-frame.html\n" +
                "Accept-Encoding: gzip, deflate, br";

        String[] split = sql.split("\n");
        Map<String, List<String>> res = new HashMap<>();
        for (String s : split) {
            String sp = ": ";
            String key = s.split(sp)[0];
            String value = s.replace(key + sp, "");
            List<String> list = res.computeIfAbsent(key, k -> new ArrayList<>());
            list.add(value);
        }
        headers = res;
        return headers;
    }

    private static String getBaseUrl() {
        return serverUrl;
    }

    public static void main(String[] args) throws Exception {
        doWork();
    }

    private static boolean doWork() throws Exception {
        GrabHPVForXF_ZMYY_Finally service = new GrabHPVForXF_ZMYY_Finally();
        List<JSONObject> hospitals = null;
        // 查询医院
        {
            String hospitalStr = service.queryHospital();
            try {
                hospitals = JSONObject.parseObject(hospitalStr).getJSONArray("list").stream().filter(o -> {
                    JSONObject j = (JSONObject) o;
                    return j.getString("cname").contains("重庆万家");
//                    return true;
                }).map(o -> (JSONObject) o).collect(Collectors.toList());
            } catch (Exception e) {
                log.error("返回值不是json字符串==>{}", hospitalStr.replaceAll("\r\n", ""));
            }
            if (CollectionUtils.isEmpty(hospitals)) {
                log.info("医院查询筛选后的数量为空");
                return false;
            } else {
                String cnames = hospitals.stream().map(j -> j.getString("cname")).collect(Collectors.joining("、"));
                log.info("医院查询筛选后的数量为：{}，医院是：{}", hospitals.size(), cnames);
            }
        }

        for (JSONObject hospital : hospitals) {
            String cname = hospital.getString("cname");
            String hospitalId = hospital.getString("id");
            BigDecimal lng = hospital.getBigDecimal("lng");
            BigDecimal lat = hospital.getBigDecimal("lat");
            // 查询产品
            String hpvInfoStr = service.queryHPV(hospitalId, lat, lng);
            List<JSONObject> hpvInfoList = null;

            {
                try {
                    hpvInfoList = JSONObject.parseObject(hpvInfoStr).getJSONArray("list").toJavaList(JSONObject.class);
                } catch (Exception e) {
                    log.error("返回值不是json字符串==>{}", hpvInfoStr.replaceAll("\r\n", ""));
                }
                if (CollectionUtils.isEmpty(hpvInfoList)) {
                    log.info("\t医院【{}】查询筛选后的数量为空", cname);
                    continue;
                } else {
                    String texts = hpvInfoList.stream().map(j -> j.getString("text") + String.format("(%s)", j.getString("date"))).collect(Collectors.joining("、"));
                    log.info("\t医院【{}】查询筛选后的数量为：{}，\n名称为：{}", cname, hpvInfoList.size(), texts);
                }
            }


            for (JSONObject hpvInfo : hpvInfoList) {
                // 查询日期
                String date = hpvInfo.getString("date");
                boolean matches = date.matches("[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2} 至 [0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}");
                if (!matches) {
                    continue;
                }
                String month = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
                String dateTimeStr = service.queryDateTime(hpvInfo.getString("id"), hospitalId, month);
                List<JSONObject> dateTimeList = null;
                {
                    try {
                        dateTimeList = JSONObject.parseObject(dateTimeStr).getJSONArray("list").toJavaList(JSONObject.class);
                    } catch (Exception e) {
                        log.error("返回值不是json字符串==>{}", dateTimeStr.replaceAll("\r\n", ""));
                    }
                    if (CollectionUtils.isEmpty(dateTimeList)) {
                        log.info("\t\t医院【{}】查询筛选后的时间列表为空", cname);
                        continue;
                    } else {
                        log.info("\t\t医院【{}】查询筛选后的时间列表为：{}", cname, dateTimeList);
                    }
                }
                for (JSONObject dateTimeJson : dateTimeList) {
                    String sc_date = dateTimeJson.getString("date");
                    String m = service.queryHasHpvByDateTime(hpvInfo.getString("id"), hospitalId, sc_date);
                    log.info("\t\t\t该时间（{}）查询出来的密文是：{}", sc_date, m.replaceAll("\n", ""));
                }
                return true;
            }
        }
        return false;
    }

    public String queryHospital() throws Exception {
        Map<String, Object> param = new HashMap<>();
        param.put("act", "CustomerList");
        param.put("lat", 39.90469);
        param.put("lng", 116.40717);
        param.put("product", 1);// 九价的代码  写死

        // 成都
        /*param.put("city", "[\"四川省\",\"成都市\",\"\"]");
        param.put("id", 0);
        param.put("cityCode", 510100);*/

        // 重庆
        param.put("city", "[\"重庆市\",\"重庆市\",\"\"]");
        param.put("id", 0);
        param.put("cityCode", 500000);

        String url = getBaseUrl();

        HttpRequest get = HttpUtil.createGet(url);
        get.form(param);
        get.header(headers, true);
        String body = get.execute().body();
        return body;
    }

    public String queryHPV(String id, BigDecimal lat, BigDecimal lng) {
        String url = getBaseUrl();
        Map<String, Object> param = new HashMap<>();
        param.put("act", "CustomerProduct");
        param.put("id", id);
        param.put("lat", lat);
        param.put("lng", lng);
        HttpRequest get = HttpUtil.createGet(url);
        get.form(param);
        get.header(headers, true);
        String body = get.execute().body();
        return body;
    }

    public String queryDateTime(String pid, String id, String month) throws Exception {
        String url = getBaseUrl();
        HttpRequest get = HttpUtil.createGet(url);

//        Proxy http_proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8866));
//        get.setProxy(http_proxy);

        Map<String, Object> param = new HashMap<>();
        param.put("act", "GetCustSubscribeDateAll");
        param.put("pid", pid);
        param.put("id", id);
        param.put("month", month);
        get.header(headers, true);
        get.form(param);
        // {"status":200,"list":[{"date":"2021-10-11","enable":true}]}
        String body = get.execute().body();
        return body;
    }

    public String queryHasHpvByDateTime(String pid, String id, String sc_date) throws Exception {
        String url = getBaseUrl();
        HttpRequest get = HttpUtil.createGet(url);


        Map<String, Object> param = new HashMap<>();
        param.put("act", "GetCustSubscribeDateDetail");
        param.put("pid", pid);
        param.put("id", id);
        param.put("scdate", sc_date);
        get.header(headers, true);
        get.form(param);
        String body = get.execute().body();
        return body;
    }

    // 提交
    @Test
    public void submit() throws Exception {
        long startTime = DateUtil.parse("2021-10-22 10:15:00", "yyyy-MM-dd HH:mm:ss").getTime();
        long endTime = DateUtil.parse("2021-10-22 10:30:00", "yyyy-MM-dd HH:mm:ss").getTime();
        while (System.currentTimeMillis() < endTime) {
            if (startTime > System.currentTimeMillis()) {
                System.out.println("还未开始，等待1秒钟后再继续执行");
                Thread.sleep(1000);
                continue;
            }
            service.execute(() -> {
                Map<String, Object> param = new HashMap<>();
                param.put("act", "GetCaptcha");
                param.put("mxid", "4m_FAPGLAACmZTQB");
                //4m_FA{PGL}AA{Ck}ZTQB   11-08
                //4m_FA{PGL}AA{Cl}ZTQB   11-09
                // pid=1 id=2562 scdate=2021-10-21 4A8AFB1BF6AF3ADC6F69067E0F3693AC4D85562B8D6CB206ECAEF6F83D83F158B31FA54E01DAC5CB0FFF91FAAE8607D85BDBA8AFC7931EF270097E118D37F5AAD88967BED167ABC1F45D4A181A50197A60CAEBDA1EACD31EF88CE539DDB14AFCEBA7BEDB0DF31D77BB39F2F2D363EC99A956BB72E4C1434F2AB5B3AB6EAD0C0A9BC738927D1DCFA132BF96169AEC8FB9C8DC4551115B18A149269E3AF9CE4627B5BAAA5A4CCAB9BD5B1C9C11C0FC2B0B1C466805518D7C6418257C04BE8DEBB6846863CF422FECC27AEA4B0724B914A818E6F91C7B4F49F31C5B831DAD285616057F97EAB69EDBC2E8CA2EF3F55DE11E973ED19467AF7B023D97FD5D420177317C65A103700312508BCE79EF108E8DAD
                // pid=1 id=2562 scdate=2021-10-22 4A8AFB1BF6AF3ADC6F69067E0F3693AC4D85562B8D6CB206ECAEF6F83D83F158B31FA54E01DAC5CB0FFF91FAAE8607D85BDBA8AFC7931EF270097E118D37F5AAD88967BED167ABC1F45D4A181A50197A60CAEBDA1EACD31EF88CE539DDB14AFCEBA7BEDB0DF31D77BB39F2F2D363EC99A956BB72E4C1434F2AB5B3AB6EAD0C0A9BC738927D1DCFA132BF96169AEC8FB9C8DC4551115B18A149269E3AF9CE4627B5BAAA5A4CCAB9BD5B1C9C11C0FC2B0B1C466805518D7C6418257C04BE8DEBB6846863CF422FECC27AEA4B0724B914A818E6F91C7B4F49F31C5B831DAD285616EB43B9E36E951C035687BFB0EC9C494D3D232988BA9B30ACAEF252B7FD084C9C05D7A3EB12204815C34323EE4DA817A9

                // 重庆万家燕医院 pid=1 id=71   scdate=2021-11-10 04E33108DA29305CD996878B03450E27C63FBF24B2686BD6AE8127810944B3663B428C31CA8A75CB99FDF4FDFB61D3AFD8539477701A7A21813705F378184D5A30A7BC6E32005FD5CA30F89957AB86ED763C0C08CE4F26A989E21DE01DC977A8AF4CB7FEE5A825F9A1A1F1CC385942DD2780778F55B5D9EA79579694461D82FF90D43F8515C6056CFC10E6C1E17AB141F14C17A89FF4F593B0CB3D6DF12F36BBAE75B7CD5D5473499539335790AEB3272282D2C0B5EFFF0C38C96A79A9AFA31A792553F00E169BC83FB87CFB4DE83DE55C3AC418322A983F3D1FF493C3801BECCA958539C5AFEF2528948DAF6552C51587084E2465B6662CE339F7D715280F41DA6B09D64E3063C8E9907A610ACC6EFEED91B66EBD38033F9B48CB34283F1F52207D800301B38D471F3010D77B29FB1E5DE30EB66D3FE6019B9888FF17C51AE1DBAF2176B76ED9B1BDFB8E5AF7F207D53A4911AC91FA4D15D8FAE43CAB20166859E477D42F86530BDF90FDE29B006269CF35A453C042FA013806380E7F55BA2C914E7C6E8CB6A7699235C73D32BC5B0A0EFD18CC9CDD591A240E3729B62006F50FAF5DA560143AA6334F4BDDF16EB715 已满
                // 重庆万家燕医院 pid=1 id=71   scdate=2021-11-11 04E33108DA29305CD996878B03450E27C63FBF24B2686BD6AE8127810944B3663B428C31CA8A75CB99FDF4FDFB61D3AFD8539477701A7A21813705F378184D5A30A7BC6E32005FD5CA30F89957AB86ED763C0C08CE4F26A989E21DE01DC977A8AF4CB7FEE5A825F9A1A1F1CC385942DD2780778F55B5D9EA79579694461D82FF90D43F8515C6056CFC10E6C1E17AB141F14C17A89FF4F593B0CB3D6DF12F36BBAE75B7CD5D5473499539335790AEB3272282D2C0B5EFFF0C38C96A79A9AFA31A792553F00E169BC83FB87CFB4DE83DE55C3AC418322A983F3D1FF493C3801BECCA958539C5AFEF2528948DAF6552C51587084E2465B6662CE339F7D715280F41DA6B09D64E3063C8E9907A610ACC6EFEED91B66EBD38033F9B48CB34283F1F52207D800301B38D471F3010D77B29FB1E5DE30EB66D3FE6019B9888FF17C51AE1DBAF2176B76ED9B1BDFB8E5AF7F207D53A4911AC91FA4D15D8FAE43CAB20166859E477D42F86530BDF90FDE29B006269CF35A453C042FA013806380E7F55BA2C6F3E96A51ADA341597BD9C66126C5AB94AE6156A2F9B36F3686E87D16F6AF628AE3DF71299855E31D50107A2420894D7 已满

                // 重庆万家燕医院 pid=1 id=71   scdate=2021-11-15 745536F71C8C5E0EEAE8EF09C8210E5CB12BF5E43EE4957149A8B0ECF69EAFD86B0746567E3F37826FB65DF821727696EBE3E2DEE5A4E8906FDB543DAEE5F18FD6ED07C2FFEE48197DCCAB518EDB4BFA1C862001D7B13DB52723F2ADB9EB11E538D78D470E45CE567E4E8C39FA5F6916C0A68E39663F1E4EF8534331F9BD3AE1A09A9D2482B4B36EBBD2770A023C587DEF53D0E2C883B57C109863B4BBE01A343BAE9BD67F99FB7B96E2428678160BDA1B9361057B71563FF3C3DA8E81993CDA00093CE7C1B0159495BF047B011120702AE6060B4F0A3EFE7A5A0AA4ED2BFA587B4D38814B9D3A7C747891B9255B863CBD6B1D24DFF1C18C7F4E65CD0DDAD9AFA812B9CC0FC01820DAE2B38BB8515F851A569E020C0B9A68D135129024F52EC5E669BA906EBD3F15E41EC0C6E8BCF3E9EE24185DCDBA24548DFBC31B1A2CCC9CD237835D03F5D6A18F36B5CFE33225443AE37703B259352A840460314A025DFFABDC44C493322ECBF43932AD7FB68268487AA0171F375BAAF995256475268F47C70C605F4685247E42587D681542FA4766D5D7A83D0077E6EF8780CAAFCA4C409AAF8F9C6769C133A348F0289F778072 已满
                // 重庆万家燕医院 pid=1 id=71   scdate=2021-11-16 745536F71C8C5E0EEAE8EF09C8210E5CB12BF5E43EE4957149A8B0ECF69EAFD86B0746567E3F37826FB65DF821727696EBE3E2DEE5A4E8906FDB543DAEE5F18FD6ED07C2FFEE48197DCCAB518EDB4BFA1C862001D7B13DB52723F2ADB9EB11E538D78D470E45CE567E4E8C39FA5F6916C0A68E39663F1E4EF8534331F9BD3AE1A09A9D2482B4B36EBBD2770A023C587DEF53D0E2C883B57C109863B4BBE01A343BAE9BD67F99FB7B96E2428678160BDA1B9361057B71563FF3C3DA8E81993CDA00093CE7C1B0159495BF047B011120702AE6060B4F0A3EFE7A5A0AA4ED2BFA587B4D38814B9D3A7C747891B9255B863CBD6B1D24DFF1C18C7F4E65CD0DDAD9AFA812B9CC0FC01820DAE2B38BB8515F851A569E020C0B9A68D135129024F52EC5E669BA906EBD3F15E41EC0C6E8BCF3E9EE24185DCDBA24548DFBC31B1A2CCC9CD237835D03F5D6A18F36B5CFE33225443AE37703B259352A840460314A025DFFABDC44C493322ECBF43932AD7FB68268487AA0171F375BAAF995256475268F4761F3FEC416C6778864B11A45ECF5BDF9559C0E811E107A2F9321257B9DE1C65A07DC200FB02FCDF5C85F19E4E44CEFB4 已满
                try {
                    HttpRequest get = HttpUtil.createGet("https://cloud.cn2030.com/sc/wx/HandlerSubscribe.ashx");
                    get.header(headers, true);
                    get.form(param);
                    get.setConnectionTimeout(1500);
                    get.setReadTimeout(4000);
                    HttpResponse execute = get.execute();
                    String body = execute.body();
                    System.out.println(body);
                } catch (Exception e) {
                    System.out.println("exception==>" + e.getMessage() + "==>e-class:" + e.getClass() + "==>e-cause:" + e.getCause());
                }
            });
        }
//        service.shutdown();
//        while (!service.isTerminated()) {
//            System.out.println("关闭线程池中...");
//            Thread.sleep(500);
//        }
    }

    @Test
    public void aes() throws Exception {
        String e = "04E33108DA29305CD996878B03450E27C63FBF24B2686BD6AE8127810944B3663B428C31CA8A75CB99FDF4FDFB61D3AFD8539477701A7A21813705F378184D5A30A7BC6E32005FD5CA30F89957AB86ED763C0C08CE4F26A989E21DE01DC977A8AF4CB7FEE5A825F9A1A1F1CC385942DD2780778F55B5D9EA79579694461D82FF90D43F8515C6056CFC10E6C1E17AB141F14C17A89FF4F593B0CB3D6DF12F36BBAE75B7CD5D5473499539335790AEB3272282D2C0B5EFFF0C38C96A79A9AFA31A792553F00E169BC83FB87CFB4DE83DE55C3AC418322A983F3D1FF493C3801BECCA958539C5AFEF2528948DAF6552C51587084E2465B6662CE339F7D715280F41DA6B09D64E3063C8E9907A610ACC6EFEED91B66EBD38033F9B48CB34283F1F52207D800301B38D471F3010D77B29FB1E5DE30EB66D3FE6019B9888FF17C51AE1DBAF2176B76ED9B1BDFB8E5AF7F207D53A4911AC91FA4D15D8FAE43CAB20166859E477D42F86530BDF90FDE29B006269CF35A453C042FA013806380E7F55BA2C6F3E96A51ADA341597BD9C66126C5AB94AE6156A2F9B36F3686E87D16F6AF628AE3DF71299855E31D50107A2420894D7";
        AES aes = SecureUtil.aes("1234".getBytes(StandardCharsets.UTF_8));
        System.out.println(aes.encryptHex("123"));

        char[] all = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~".toCharArray();
        int len = 16;
    }

    @Test
    public void getKeyStr() throws Exception {
        File aesKeyFile = new File("E:/temp/aeskey.txt");
        char[] chars = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~".toCharArray();
        Lock lock = new ReentrantLock();
        int keyCollectionLen = 1024;


        StringBuilder keyCaption = new StringBuilder();
        List<String> keyCollection = new ArrayList<>(keyCollectionLen);
        int[] startIndex = new int[16];
        int[] endIndex = new int[16];
        while (true) {
            for (int i : startIndex) {
                keyCaption.append(chars[i]);
            }
            String key = keyCaption.toString();
            keyCollection.add(key);
            keyCaption.setLength(0);
            if (keyCollection.size() == keyCollectionLen) {
                try {
                    lock.lock();
                    FileUtil.appendLines(keyCollection, aesKeyFile, StandardCharsets.UTF_8);
                    keyCollection.clear();
                } finally {
                    lock.unlock();
                }
            }
            if (Arrays.equals(startIndex, endIndex)) {
                break;
            }
            add(startIndex, chars.length - 1, startIndex.length - 1);
        }
    }

    private void add(int[] arr, int maxIndex, int index) {
        if (index == -1) {
            return;
        }
        int i = arr[index];
        if ((i + 1) > maxIndex) {
            arr[index] = 0;
            add(arr, maxIndex, index - 1);

        } else {
            arr[index] += 1;
        }
    }
}
